package com.siqi.hr.system.organization.dao.mysql;

import com.siqi.hr.common.Constants;
import com.siqi.hr.common.utils.TableConstant;
import com.siqi.hr.system.common.authority.DataScope;
import com.siqi.hr.system.common.sql.STable;
import com.siqi.hr.system.custom.dao.intf.EntityOperationDao;
import com.siqi.hr.system.custom.dao.intf.EntityRecordDao;
import com.siqi.hr.system.custom.entity.EntityOperation;
import com.siqi.hr.system.custom.entity.EntityRecord;
import com.siqi.hr.system.custom.utils.MyComparator;
import com.siqi.hr.system.organization.dao.intf.RoleDao;
import com.siqi.hr.system.common.model.Module;
import com.siqi.hr.system.common.model.ModuleType;
import com.siqi.hr.system.common.utils.EnumUtils;
import com.siqi.hr.system.organization.entity.Role;
import com.siqi.hr.system.organization.entity.RoleEntityScope;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Repository;
import org.springframework.util.Assert;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.*;

/**
 * 角色信息维护dao实现类层
 * @author     xiaogq
 * Created by xiaogoingqin on 2016/7/21.
 */
@Repository("roleDao")
public class RoleDaoImpl implements RoleDao {

    @Autowired
    private JdbcTemplate jdbcTemplate;

    @Autowired
    private EntityRecordDao entityRecordDao;

    @Autowired
    private EntityOperationDao entityOperationDao;

    /**
     * 根据当前登录系统员工所属角色Id获得可以登录的模块
     * @param roleId （角色id）
     * @return
     * @throws Exception
     */
    @Override
    public List<Module> getRoleModule(String roleId)  throws Exception{
        Assert.hasText(roleId);
        StringBuilder sql = new StringBuilder("select loginModule_varchar from ").append("t_1").append(" where id = ? ");
        try {
            String roleModules = jdbcTemplate.queryForObject(sql.toString(), new Object[] { roleId }, String.class);
            List<Module> moduleList = new ArrayList<Module>();
            Collection<ModuleType> modules = EnumUtils.tranform(roleModules,ModuleType.class);
            for (ModuleType mod : modules) {
                Module module = new Module();
                module.setId(mod.getCode());
                module.setName(mod.name());
                module.setInchinese(mod.getDesc());
                moduleList.add(module);
            }
            return moduleList;
        } catch (DataAccessException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * @deprecated  获取当前角色不可以查看该实体字段信息
     * @param roleId（角色id）
     * @param entityId（实体id）
     * @return
     */
    public Map<String, Boolean> getRoleEntityFieldListAuth(String roleId, int entityId)  throws Exception{
        final Map<String, Boolean> authMap = new HashMap<String, Boolean>();
        try {
            StringBuffer sql = new StringBuffer("SELECT rf.* FROM sys_org_role_field rf LEFT JOIN sys_custom_field f on f.id = rf.field_id WHERE rf.role_id = ? ");
            sql.append(" and rf.entity_id = ? and f.controled = true ");
            jdbcTemplate.query(sql.toString(), new Object[] { roleId,entityId }, new RowMapper() {
                public Object mapRow(ResultSet rs, int rowNum) throws SQLException {
                    Boolean boo = rs.getBoolean("forbid_view_charge");
                    authMap.put(rs.getString("field_name"), boo);
                    return null;
                }
            });
        } catch (Exception e) {
            e.printStackTrace();
        }
        return authMap;
    }

    @Override
    public RoleEntityScope queryRoleDataScope(String roleId, EntityRecord entityRecord) {
        RoleEntityScope res = new RoleEntityScope();
        res.setId(roleId + "_" + entityRecord.getTableCode());
        res.setViewLevel(DataScope.ALL.toString());
        res.setEditLevel(DataScope.ALL.toString());
        res.setDeleteLevel(DataScope.ALL.toString());
        if (roleId.equals(Constants.ROOTROLEID)) {
            return res;
        }
        if (entityRecord != null) {
            if (entityRecord.getPermission()) {
                StringBuffer sql = new StringBuffer("select view_level,edit_level,delete_level from sys_org_role_entity_scope ");
                sql.append("where role_id = '").append(roleId).append("' and entity_id = ").append(entityRecord.getTableCode());
                try {
                    Map<String,Object> map = this.jdbcTemplate.queryForMap(sql.toString());
                    res.setViewLevel(map.get("view_level").toString());
                    res.setEditLevel(map.get("edit_level").toString());
                    res.setDeleteLevel(map.get("delete_level").toString());
                } catch (DataAccessException e) {
                    res.setViewLevel(DataScope.NONE.toString());
                    res.setEditLevel(DataScope.NONE.toString());
                    res.setDeleteLevel(DataScope.NONE.toString());
                }
            }
        }
        return res;
    }

    @Override
    public List<Role> getAllAdminRoles() {
        List<Role> roleList = new ArrayList<Role>();
        StringBuilder sql = new StringBuilder();
        sql.append("select id,name_varchar,isadmin_bit,loginModule_varchar,description_varchar from ").append(STable.TABLE_HEAD+TableConstant.ROLE_TCODE).append(" where isadmin_bit = true and flag_bit = false");
        try {
            roleList = jdbcTemplate.query(sql.toString(),new Role.FullRecord());
        } catch (DataAccessException e) {
            e.printStackTrace();
        }
        return roleList;
    }

    @Override
    public void setRoleEntityOperation(List<Role> roleList, EntityRecord entityRecord) {
        List<String> sqlList = new ArrayList<String>();
        for (int i = 0; i < roleList.size(); i++) {
            StringBuilder sb1 = new StringBuilder();
//            StringBuilder sb2 = new StringBuilder();
//            StringBuilder sb3 = new StringBuilder();
            StringBuilder sb4 = new StringBuilder();
            StringBuilder sb5 = new StringBuilder();
            StringBuilder sb6 = new StringBuilder();
            //添加自定义实体时增加添加操作
            sb1.append("insert into sys_org_role_entity_operation(role_id,entity_id,operation_id,flag) values ( '");
            sb1.append(roleList.get(i).getId()).append("',"+entityRecord.getTableCode()+","+"'002N89CWI0Nj',1)");
//            sb2.append("insert into sys_org_role_entity_operation(role_id,entity_id,operation_id,flag) values ( '");
//            sb2.append(roleList.get(i).getId()).append("',"+entityRecord.getTableCode()+","+"'002N89GX9nZb',1)");
//            sb3.append("insert into sys_org_role_entity_operation(role_id,entity_id,operation_id,flag) values ( '");
//            sb3.append(roleList.get(i).getId()).append("',"+entityRecord.getTableCode()+","+"'002N89GmWYK1',1)");
            //添加自定义实体时增加查看操作
            sb4.append("insert into sys_org_role_entity_operation(role_id,entity_id,operation_id,flag) values ( '");
            sb4.append(roleList.get(i).getId()).append("',"+entityRecord.getTableCode()+","+"'002N89HsUpBS',1)");
            //添加自定义实体时增加编辑操作
            sb5.append("insert into sys_org_role_entity_operation(role_id,entity_id,operation_id,flag) values ( '");
            sb5.append(roleList.get(i).getId()).append("',"+entityRecord.getTableCode()+","+"'002N89I711Um',1)");
            //添加自定义实体时增加删除操作
            sb6.append("insert into sys_org_role_entity_operation(role_id,entity_id,operation_id,flag) values ( '");
            sb6.append(roleList.get(i).getId()).append("',"+entityRecord.getTableCode()+","+"'002N89IKZt8c',1)");
            sqlList.add(sb1.toString());
//            sqlList.add(sb2.toString());
//            sqlList.add(sb3.toString());
            sqlList.add(sb4.toString());
            sqlList.add(sb5.toString());
            sqlList.add(sb6.toString());
        }
        String[] sqls = sqlList.toArray(new String[sqlList.size()] );
        try {
            if(sqls.length > 0){
                jdbcTemplate.batchUpdate(sqls);
            }
        } catch (DataAccessException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void setDefaultRoleEntityScope(List<Role> roleList, EntityRecord entityRecord) {
        String[] sqls = new String[roleList.size()];
        for (int i = 0; i < roleList.size(); i++) {
            StringBuilder sb = new StringBuilder();
            sb.append("insert into sys_org_role_entity_scope(role_id,entity_id,view_level,edit_level,delete_level) values ( '");
            sb.append((roleList.get(i)).getId()).append("',");
            sb.append(entityRecord.getTableCode()).append(" , 'ALL','ALL','ALL' ) ");
            sqls[i] = sb.toString();
        }
        try {
            jdbcTemplate.batchUpdate(sqls);
        } catch (DataAccessException e) {
            e.printStackTrace();
        }
    }

    @Override
    public List<Role> queryRoleAll() {
        String sql = " select id ,name_varchar,description_varchar from t_1";
        return this.jdbcTemplate.query(sql,new Role.mainRecord());
    }

    @Override
    public String queryRoleMenus(String roleid, String kind) {
        Assert.hasText(roleid);
        Assert.hasText(kind);

        final Boolean isAdmin = roleid.equals(Constants.ROOTROLEID);

        StringBuilder sql = new StringBuilder();
        sql.append(" select id,name,pid,belong_mudule from sys_org_menu m where flag = true ");
        sql.append(" and ( pid is null or ( pid is not null and exists(select 0 from sys_org_menu where id = m.pid and flag = true )) ) ");
        if (kind.equals("sys")) {
            sql.append(" and belong_mudule like '1%' ");
        } else {
            List<String> markSqlList = new ArrayList<String>();
            for (String modMark : ModuleType.getCRMModuleMark()) {
                markSqlList.add(" belong_mudule like '" + modMark + "' ");
            }
            sql.append(" and ( " + StringUtils.join(markSqlList, " or ") + " ) ");
        }
        sql.append(" order by `level`, position ");

        List <Map<String,Object>> allMenuList = this.jdbcTemplate.query(sql.toString(), new RowMapper() {
            public Object mapRow(ResultSet rs, int arg1) throws SQLException {
                final Map<String,Object> map = new HashMap<String,Object>();
                map.put("id", Integer.valueOf(rs.getInt("id")));
                map.put("name", rs.getString("name"));
                map.put("pid", Integer.valueOf(rs.getInt("pid")));
                map.put("checked", isAdmin);
                return map;
            }
        });
        //如果不是系统管理员角色
        if (!isAdmin){//选中已经选择的系统配置、crm权限
            String psmsql = "select menu_id as id from sys_org_role_menu where flag = true and role_id = '" + roleid + "'";
            List<Integer> roleMenuList = jdbcTemplate.queryForList(psmsql, Integer.class);
            if(roleMenuList.size() > 0){
                for (Map<String,Object> menuMap : allMenuList){
                    String id = menuMap.get("id").toString();
                    if(roleMenuList.contains(Integer.parseInt(id))){
                        menuMap.put("checked", true);
                    }
                }
            }
        }

        JSONArray array = new JSONArray();
        for (int i = 0; i < allMenuList.size(); i++) {
            Map<String,Object> jmap = allMenuList.get(i);
            JSONObject object = new JSONObject();
            object.put("id", jmap.get("id"));
            object.put("name", jmap.get("name"));
            object.put("pid", jmap.get("pid"));
            object.put("checked", jmap.get("checked"));
            array.add(object);
        }
        return array.toString();
    }

    @Override
    public int updateRolePms(String roleid, String kind, String menuids) {
        Assert.hasText(roleid);
        Assert.hasText(kind);
        int lens = 0;
        StringBuilder msql = new StringBuilder();
        msql.append("update sys_org_role_menu set flag = false where role_id = '").append(roleid).append("' ");
        if (kind.equals("sys")) {
            msql.append(" and menu_id in ( select id from sys_org_menu where belong_mudule like '1%' ) ");
        } else {
            msql.append(" and menu_id in ( select id from sys_org_menu where ");
            List<String> markSqlList = new ArrayList<String>();
            for (String modMark : ModuleType.getCRMModuleMark()) {
                markSqlList.add(" belong_mudule like '" + modMark + "' ");
            }
            msql.append(StringUtils.join(markSqlList, " or ") + " ) ");
        }
        lens = jdbcTemplate.update(msql.toString());

        if ((menuids != null) && (!menuids.equals(""))) {
            String[] menuidArr = menuids.split(",");
            for (int i = 0; i < menuidArr.length; i++) {
                String sql = "{call updateRoleMenuPermission(?,?,?)}";
                lens = jdbcTemplate.update(sql, new Object[] { roleid,menuidArr[i], true});
            }
        }
        return lens;
    }

    @Override
    public List<Map<String, Object>> queryRoleOperationPms(String roleid) {
        Assert.hasText(roleid);
        List<Map<String,Object>> reodList = new ArrayList<Map<String,Object>>();
        //获得所有受权限控制的实体
        List<EntityRecord> entityList = entityRecordDao.queryPmsEntity(true);
        //获得所有受权限控制的操作
        List<EntityOperation> operList = entityOperationDao.queryAllOperationByPms(true);
        //根据角色id获得所有已经启用的操作
        List<Map<String,Object>> roleOperList = entityOperationDao.queryRoleOperationList(roleid);

        Map<String,Object> operMap = new TreeMap<String,Object>(new MyComparator());

        Map<String,Object> shortcutMap = new TreeMap<String,Object>(new MyComparator());

        for (int i = 0; i < operList.size(); i++) {
            operMap.put(operList.get(i).getId(),  operList.get(i).getName());
            shortcutMap.put(operList.get(i).getId(), "");
        }

        operMap.put("entityId", "对象类型");
        operMap.put("entityName", "对象");

        shortcutMap.put("entityId", "");
        shortcutMap.put("entityName", "");

        reodList.add(operMap);
        reodList.add(shortcutMap);

        for (EntityRecord entity : entityList) {
            Map<String,Object> eoMap = new TreeMap<String,Object>(new MyComparator());
            eoMap.put("entityId", entity.getTableCode());
            eoMap.put("entityName", entity.getInchinese());
            for (Map.Entry<String,Object> operEntry : operMap.entrySet()) {
                if ((!operEntry.getKey().equals("entityId")) && (!operEntry.getKey().equals("entityName"))) {
                    String operId = operEntry.getKey().toString();
                    boolean noflag = true;
                    if (roleOperList != null) {
                        for (int i = 0; i < roleOperList.size(); i++) {
                            //如果是停用/启用按钮
                            if(operId.contains("/")){
                                String [] enlableOperIds =  operId.split("/");
                                if ((roleOperList.get(i).get("oid").toString().equals(enlableOperIds[0])) && (Integer.parseInt(roleOperList.get(i).get("entityId").toString()) == entity.getTableCode())) {
                                    eoMap.put(operId,"enable");
                                    noflag = false;
                                }
                            }else{
                                if ((roleOperList.get(i).get("oid").toString().equals(operId)) && (Integer.parseInt(roleOperList.get(i).get("entityId").toString()) == entity.getTableCode())) {
                                    eoMap.put(operId,"enable");
                                    noflag = false;
                                }
                            }
                        }
                    }
                    if (noflag) {
                        eoMap.put(operId, "none");
                    }
                }
            }
            reodList.add(eoMap);
        }
        //System.out.println("reodList==="+reodList);
        return reodList;
    }

    @Override
    public int updateRoleOperationPms(String roleid, List<Map<String, Object>> reoList) {
        Assert.notEmpty(reoList);
        List<String> dsqls = new ArrayList<String>();
        List<String> isqls = new ArrayList<String>();
        int [] lens = new int [0];
        for (int i = 0; i < reoList.size(); i++) {
            Map<String, Object> reo = reoList.get(i);
            String entityId = reo.get("entityId") == null ? "0" : reo.get("entityId").toString();
            String operId = reo.get("operId") == null ? "" : reo.get("operId").toString();
            String operFlag = reo.get("operFlag") == null ? "" : reo.get("operFlag").toString();
            StringBuilder deletesql = new StringBuilder();
            deletesql.append(" delete from sys_org_role_entity_operation ");
            deletesql.append(" where role_id = '").append(roleid).append("' and entity_id = ").append(reo.get("entityId"));
            dsqls.add(deletesql.toString());

            StringBuilder insertsql = new StringBuilder();
            insertsql.append(" insert into sys_org_role_entity_operation(role_id,entity_id,operation_id,flag) ");
            insertsql.append(" values('").append(roleid).append("',").append(entityId).append(",");
            insertsql.append("'").append(operId).append("',"+operFlag+") ");
            isqls.add(insertsql.toString());
        }
        jdbcTemplate.batchUpdate(dsqls.toArray(new String[dsqls.size()]));
        lens = jdbcTemplate.batchUpdate(isqls.toArray(new String[isqls.size()]));
        return lens.length;
    }

    @Override
    public List<RoleEntityScope> queryRoleDataPms(String roleid) {
        Assert.hasText(roleid);

        Boolean isAdmin = roleid.equals(Constants.ROOTROLEID);
        //获取受权限控制的实体
        List<EntityRecord> entityList = entityRecordDao.queryPmsEntity(true);

        List<Map<String,Object>> resdList = new ArrayList<Map<String,Object>>();
        if (!isAdmin) {
            StringBuilder resdsql = new StringBuilder();
            resdsql.append("select entity_id, view_level, edit_level, delete_level from sys_org_role_entity_scope where role_id = '").append(roleid).append("' ");
            try {
                resdList = this.jdbcTemplate.queryForList(resdsql.toString());
            } catch (DataAccessException e) {
                e.printStackTrace();
            }
        }

        List<RoleEntityScope> resultList = new ArrayList<RoleEntityScope>();
        if (entityList != null) {
            for (EntityRecord entity : entityList) {
                RoleEntityScope resd = new RoleEntityScope();
                resd.setEntityId(entity.getTableCode());
                resd.setEntityName(entity.getInchinese());
                if (!isAdmin) {
                    Boolean existFlag = false;
                    if ((resdList != null) && (resdList.size() > 0)) {
                        for (int i = 0; i < resdList.size(); i++) {
                            if (Integer.parseInt(resdList.get(i).get("entity_id").toString()) == entity.getTableCode()) {
                                existFlag = true;
                                resd.setViewLevel(resdList.get(i).get("view_level").toString());
                                resd.setEditLevel(resdList.get(i).get("edit_level").toString());
                                resd.setDeleteLevel(resdList.get(i).get("delete_level").toString());
                            }
                        }
                    }
                    if (!existFlag.booleanValue()) {
                        resd.setViewLevel(DataScope.NONE.name());
                        resd.setEditLevel(DataScope.NONE.name());
                        resd.setDeleteLevel(DataScope.NONE.name());
                    }
                } else {
                    resd.setViewLevel(DataScope.ALL.name());
                    resd.setEditLevel(DataScope.ALL.name());
                    resd.setDeleteLevel(DataScope.ALL.name());
                }
                resultList.add(resd);
            }
        }
        return resultList;
    }

    @Override
    public List<Map<String, Object>> queryAllDataScope() {
        List<Map<String,Object>> listScope = new ArrayList<Map<String,Object>>();
        for (DataScope pl : DataScope.values()) {
            Map<String,Object> enuMap = new HashMap<String,Object>();
            enuMap.put("name", pl.toString());
            enuMap.put("inChinese", pl.getChinese());
            listScope.add(enuMap);
        }
        return listScope;
    }

    @Override
    public int updateRoleDataPms(String roleid, List<Map<String, Object>> redList) {
        Assert.notEmpty(redList);

        String[] dsqls = new String[redList.size()];
        String[] usqls = new String[redList.size()];
        String[] editqls = new String[redList.size()];
        String[] delqls = new String[redList.size()];

        for (int i = 0; i < redList.size(); i++) {
            String entityidval = redList.get(i).get("entityId").toString();
            String viewLevel = redList.get(i).get("viewLevel").toString();
            String editLevel = redList.get(i).get("editLevel").toString();
            String deleteLevel = redList.get(i).get("deleteLevel").toString();

            StringBuilder deletesql = new StringBuilder();
            deletesql.append(" delete from sys_org_role_entity_scope ");
            deletesql.append(" where role_id = '").append(roleid).append("' and entity_id = ").append(entityidval);
            dsqls[i] = deletesql.toString();

            StringBuilder insertsql = new StringBuilder();
            insertsql.append(" insert into sys_org_role_entity_scope(role_id,entity_id,view_level,edit_level,delete_level) ");
            insertsql.append(" values('").append(roleid).append("',").append(entityidval).append(",");
            insertsql.append("'").append(viewLevel).append("', ");
            insertsql.append("'").append(editLevel).append("', ");
            insertsql.append("'").append(deleteLevel).append("') ");
            usqls[i] = insertsql.toString();

            //如果是该角色对实体无编辑权限,则删除角色，实体编辑按钮关系
            if (editLevel.equals(DataScope.NONE.name())) {
                editqls[i] = "delete from sys_org_role_entity_operation where role_id = '"+roleid +"' and entity_id = "+entityidval+" and operation_id = '002N89I711Um'";
            }else {
                editqls[i] = "insert into sys_org_role_entity_operation(role_id,entity_id,operation_id,flag) values('"+roleid+"',"+entityidval+",'002N89I711Um',true)";
            }
            if (deleteLevel.equals(DataScope.NONE.name())) {
                delqls[i] = "delete from sys_org_role_entity_operation where role_id = '" + roleid + "' and entity_id = " + entityidval + " and operation_id = '002N89IKZt8c'";
            }else {
                delqls[i] = "insert into sys_org_role_entity_operation(role_id,entity_id,operation_id,flag) values('"+roleid+"',"+entityidval+",'002N89IKZt8c',true)";
            }
        }

        jdbcTemplate.batchUpdate(dsqls);
        int [] lens = jdbcTemplate.batchUpdate(usqls);
        jdbcTemplate.batchUpdate(editqls);
        jdbcTemplate.batchUpdate(delqls);
        return lens.length;
    }
}
